package asrModel

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"myproject/config"
	"myproject/ttsModel"
	"net/http"
	"os"
	"time"

	"github.com/google/uuid"
	"github.com/gordonklaus/portaudio"
	"github.com/gorilla/websocket"
)

const (
	wsURL      = "wss://dashscope.aliyuncs.com/api-ws/v1/inference/" // WebSocket服务器地址
	audioFile  = "asr_example.wav"                                   // 替换为您的音频文件路径
	sampleRate = 44100
	frameSize  = 2048
	recordTime = 20 * time.Second // 录制时间，可根据需要调
)

var dialer = websocket.DefaultDialer

// var voiceIndex int = 0

func StartGummy(connWx *websocket.Conn, sourceLanguage string, targetLanguage string, selectVoiceIndex int) {
	// voiceIndex = selectVoiceIndex
	connGummy, err := ConnectWebSocket(config.AppConfig.Gummy.ApiKey)
	if err != nil {
		log.Fatal("连接WebSocket失败：", err)
	}
	defer CloseConnection(connGummy)

	// 启动一个goroutine来接收结果
	taskStarted := make(chan bool)
	taskDone := make(chan bool)
	StartResultReceiver(connGummy, taskStarted, taskDone, connWx, selectVoiceIndex)

	// 发送run-task指令
	taskID, err := SendRunTaskCmd(connGummy, sourceLanguage, targetLanguage)
	if err != nil {
		log.Fatal("发送run-task指令失败：", err)
	}
	log.Println("发送run-task指令成功", taskID)

	// 等待task-started事件
	WaitForTaskStarted(taskStarted)

	for {
		messageType, message, err := connWx.ReadMessage()
		if err != nil {
			log.Println("客户端断开连接:", err)
			break
		}
		//fmt.Println(message)
		// 忽略非二进制消息
		if messageType != websocket.BinaryMessage {
			continue
		}

		// fmt.Println("向大模型发送数据")
		if err := connGummy.WriteMessage(websocket.BinaryMessage, message); err != nil {
			log.Printf("转发失败")
			break
		}
	}

	// 发送finish-task指令
	if err := SendFinishTaskCmd(connGummy, taskID); err != nil {
		log.Fatal("发送finish-task指令失败：", err)
	}
	// 等待任务完成或失败
	<-taskDone
}

func Gummy() {
	// 若没有将API Key配置到环境变量，可将下行替换为：apiKey := "your_api_key"。不建议在生产环境中直接将API Key硬编码到代码中，以减少API Key泄露风险。
	//apiKey := "sk-0ad14d234ede4a8cad3d76e5e8136ff0"

	err := portaudio.Initialize()
	if err != nil {
		log.Fatal("初始化PortAudio失败：", err)
	}
	defer portaudio.Terminate()

	// 连接WebSocket服务
	conn, err := ConnectWebSocket(config.AppConfig.Gummy.ApiKey)
	if err != nil {
		log.Fatal("连接WebSocket失败：", err)
	}
	defer CloseConnection(conn)

	// 启动一个goroutine来接收结果
	taskStarted := make(chan bool)
	taskDone := make(chan bool)
	StartResultReceiver(conn, taskStarted, taskDone, conn, 0)

	// 发送run-task指令
	taskID, err := SendRunTaskCmd(conn, "zh", "en")
	if err != nil {
		log.Fatal("发送run-task指令失败：", err)
	}

	// 等待task-started事件
	WaitForTaskStarted(taskStarted)

	// 发送待识别音频文件流
	//if err := sendAudioData(conn); err != nil {
	//	log.Fatal("发送音频失败：", err)
	//}

	if err := recordAndSendAudio(conn); err != nil {
		log.Fatal("发送音频失败：", err)
	}

	// 发送finish-task指令
	if err := SendFinishTaskCmd(conn, taskID); err != nil {
		log.Fatal("发送finish-task指令失败：", err)
	}

	// 等待任务完成或失败
	<-taskDone
}

// 定义结构体来表示JSON数据
type Header struct {
	Action       string                 `json:"action"`
	TaskID       string                 `json:"task_id"`
	Streaming    string                 `json:"streaming"`
	Event        string                 `json:"event"`
	ErrorCode    string                 `json:"error_code,omitempty"`
	ErrorMessage string                 `json:"error_message,omitempty"`
	Attributes   map[string]interface{} `json:"attributes"`
}

type Output struct {
	Translations  []Translation `json:"translations"`
	Transcription Transcription `json:"transcription"`
}

type Translation struct {
	SentenceID   int    `json:"sentence_id"`
	BeginTime    int64  `json:"begin_time"`
	EndTime      int64  `json:"end_time"`
	Text         string `json:"text"`
	Lang         string `json:"lang"`
	PreEndFailed bool   `json:"pre_end_failed"`
	Words        []Word `json:"words"`
	SentenceEnd  bool   `json:"sentence_end"`
}

type Transcription struct {
	SentenceID  int    `json:"sentence_id"`
	BeginTime   int64  `json:"begin_time"`
	EndTime     int64  `json:"end_time"`
	Text        string `json:"text"`
	Words       []Word `json:"words"`
	SentenceEnd bool   `json:"sentence_end"`
}

type Word struct {
	BeginTime   int64  `json:"begin_time"`
	EndTime     int64  `json:"end_time"`
	Text        string `json:"text"`
	Punctuation string `json:"punctuation"`
	Fixed       bool   `json:"fixed"`
	SpeakerID   *int   `json:"speaker_id"`
}

type Payload struct {
	TaskGroup  string  `json:"task_group"`
	Task       string  `json:"task"`
	Function   string  `json:"function"`
	Model      string  `json:"model"`
	Parameters Params  `json:"parameters"`
	Input      Input   `json:"input"`
	Output     *Output `json:"output,omitempty"`
}

type Params struct {
	Format                     string   `json:"format"`
	SampleRate                 int      `json:"sample_rate"`
	VocabularyID               string   `json:"vocabulary_id,omitempty"`
	SourceLanguage             string   `json:"source_language,omitempty"`
	TranslationTargetLanguages []string `json:"translation_target_languages,omitempty"`
	TranscriptionEnabled       bool     `json:"transcription_enabled,omitempty"`
	TranslationEnabled         bool     `json:"translation_enabled,omitempty"`
}

type Input struct {
}

type Event struct {
	Header  Header  `json:"header"`
	Payload Payload `json:"payload"`
}

// 连接WebSocket服务
func ConnectWebSocket(apiKey string) (*websocket.Conn, error) {
	header := make(http.Header)
	header.Add("X-DashScope-DataInspection", "enable")
	header.Add("Authorization", fmt.Sprintf("bearer %s", apiKey))
	conn, _, err := dialer.Dial(wsURL, header)
	return conn, err
}

// 启动一个goroutine异步接收WebSocket消息
func StartResultReceiver(connGummy *websocket.Conn, taskStarted chan<- bool, taskDone chan<- bool, connWx *websocket.Conn, selectVoiceIndex int) {
	go func() {
		for {
			_, message, err := connGummy.ReadMessage()
			if err != nil {
				log.Println("解析服务器消息失败：", err)
				return
			}
			var event Event
			err = json.Unmarshal(message, &event)
			if err != nil {
				log.Println("解析事件失败：", err)
				continue
			}
			if handleEvent(connGummy, event, taskStarted, taskDone, connWx, selectVoiceIndex) {
				return
			}
		}
	}()
}

// 发送run-task指令
func SendRunTaskCmd(conn *websocket.Conn, languageSource string, languageTarget string) (string, error) {
	runTaskCmd, taskID, err := generateRunTaskCmd(languageSource, languageTarget)
	if err != nil {
		return "", err
	}
	err = conn.WriteMessage(websocket.TextMessage, []byte(runTaskCmd))
	return taskID, err
}

// 生成run-task指令
func generateRunTaskCmd(languageSource string, languageTarget string) (string, string, error) {
	taskID := uuid.New().String()
	runTaskCmd := Event{
		Header: Header{
			Action:    "run-task",
			TaskID:    taskID,
			Streaming: "duplex",
		},
		Payload: Payload{
			TaskGroup: "audio",
			Task:      "asr",
			Function:  "recognition",
			Model:     "gummy-realtime-v1",
			Parameters: Params{
				Format:                     "pcm",
				SampleRate:                 44100,
				TranscriptionEnabled:       true,
				TranslationEnabled:         true,
				SourceLanguage:             languageSource,
				TranslationTargetLanguages: []string{languageTarget},
			},
			Input: Input{},
		},
	}
	runTaskCmdJSON, err := json.Marshal(runTaskCmd)
	return string(runTaskCmdJSON), taskID, err
}

// 等待task-started事件
func WaitForTaskStarted(taskStarted chan bool) {
	select {
	case <-taskStarted:
		// fmt.Println("任务开启成功")
		log.Println("收到task-started指令")
	case <-time.After(10 * time.Second):
		log.Fatal("等待task-started超时，任务开启失败")
	}
}

// 发送音频数据
func sendAudioData(conn *websocket.Conn) error {
	file, err := os.Open(audioFile)
	if err != nil {
		return err
	}
	defer file.Close()

	buf := make([]byte, 1024) // 假设100ms的音频数据大约为1024字节
	for {
		n, err := file.Read(buf)
		if n == 0 {
			break
		}
		if err != nil && err != io.EOF {
			return err
		}
		err = conn.WriteMessage(websocket.BinaryMessage, buf[:n])
		if err != nil {
			return err
		}
		time.Sleep(100 * time.Millisecond)
	}
	return nil
}

func recordAndSendAudio(conn *websocket.Conn) error {
	input := make([]int16, frameSize)
	stream, err := portaudio.OpenDefaultStream(1, 0, float64(sampleRate), frameSize, &input)
	if err != nil {
		return err
	}
	defer stream.Close()

	err = stream.Start()
	if err != nil {
		return err
	}
	defer stream.Stop()

	// 预分配字节缓冲区，避免重复分配内存
	buf := make([]byte, len(input)*2)

	endTime := time.Now().Add(recordTime)
	for time.Now().Before(endTime) {
		// 读取音频数据
		//fmt.Println("................................")
		if err := stream.Read(); err != nil {
			return err
		}

		// 转换为字节切片
		for i, v := range input {
			buf[i*2] = byte(v)
			buf[i*2+1] = byte(v >> 8)
		}
		//fmt.Println(buf)
		// 发送数据
		if err := conn.WriteMessage(websocket.BinaryMessage, buf); err != nil {
			return err
		}
		//time.Sleep(100 * time.Millisecond)
	}

	return nil
}

// 发送finish-task指令
func SendFinishTaskCmd(conn *websocket.Conn, taskID string) error {
	finishTaskCmd, err := generateFinishTaskCmd(taskID)
	if err != nil {
		return err
	}
	err = conn.WriteMessage(websocket.TextMessage, []byte(finishTaskCmd))
	return err
}

// 生成finish-task指令
func generateFinishTaskCmd(taskID string) (string, error) {
	finishTaskCmd := Event{
		Header: Header{
			Action:    "finish-task",
			TaskID:    taskID,
			Streaming: "duplex",
		},
		Payload: Payload{
			Input: Input{},
		},
	}
	finishTaskCmdJSON, err := json.Marshal(finishTaskCmd)
	return string(finishTaskCmdJSON), err
}

type resultTextWx struct {
	MessageType     string `json:"message_type"`
	TranscriptionWx string `json:"transcriptionWx"`
	TranslationWx   string `json:"translationWx"`
	SentenceEnd     bool   `json:"sentenceEnd"`
}

type resultAudioWx struct {
	// MessageType int    `json:"message_type"`
	AudioData []byte `json:"audio_data"`
}

// 处理事件
func handleEvent(connGummy *websocket.Conn, event Event, taskStarted chan<- bool, taskDone chan<- bool, connWx *websocket.Conn, voiceIndex int) bool {
	switch event.Header.Event {
	case "task-started":
		// fmt.Println("收到task-started事件")
		taskStarted <- true
	case "result-generated":
		// fmt.Println("服务器返回结果：")
		if event.Payload.Output != nil {
			if len(event.Payload.Output.Translations) == 0 {
				return false
			}
			//fmt.Println(event.Payload.Output.Transcription.Text)
			//fmt.Println(event.Payload.Output.Translations[0].Text)

			// return false
			resTextWx := resultTextWx{
				MessageType:     "translation",
				TranscriptionWx: event.Payload.Output.Transcription.Text,
				TranslationWx:   event.Payload.Output.Translations[0].Text,
				SentenceEnd:     event.Payload.Output.Translations[0].SentenceEnd,
			}

			// return false
			resWxJSON, err := json.Marshal(resTextWx)
			if err != nil {
				log.Printf("JSON序列化失败: %v", err)
				return false
			}
			// return false
			err = connWx.WriteMessage(websocket.TextMessage, resWxJSON)
			if err != nil {
				log.Println()
				return false
			}

			if event.Payload.Output.Translations[0].SentenceEnd {
				audioData := ttsModel.SpeechSynthesis(resTextWx.TranslationWx, event.Payload.Output.Translations[0].Lang, voiceIndex)
				//resAudioWx := resultAudioWx{
				//	// MessageType: 2,
				//	AudioData: audioData,
				//}
				//resAudioWxJSON, err := json.Marshal(resAudioWx)
				//if err != nil {
				//	log.Printf("JSON序列化失败: %v", err)
				//	return false
				//}
				// AudioData := base64.StdEncoding.EncodeToString(audioData)
				err = connWx.WriteMessage(websocket.BinaryMessage, audioData)
				if err != nil {
					log.Println()
					return false
				}
			}

			// return false
			// fmt.Println("已发送")

			//if event.Payload.Output.Translations[0].SentenceEnd {
			//	audioData := ttsModel.SpeechSynthesis(resTextWx.TranslationWx, "en-US-JennyNeural")
			//	resAudioWx := resultAudioWx{
			//		MessageType: "audio",
			//		AudioData:   audioData,
			//	}
			//	resAudioJSON, err := json.Marshal(resAudioWx)
			//	if err != nil {
			//		log.Printf("JSON序列化失败: %v", err)
			//		return false
			//	}
			//
			//	// 发送二进制消息
			//	err = connWx.WriteMessage(websocket.BinaryMessage, resAudioJSON)
			//	if err != nil {
			//		log.Printf("WebSocket发送失败: %v", err)
			//		return false
			//	}
			//
			//	log.Println("音频数据已发送")
			//
			//}

			// 解析 Translations 和 Transcription
			//for _, translation := range event.Payload.Output.Translations {
			//	fmt.Printf("	翻译结果 - Sentence ID：%d, Text：%s\n", translation.SentenceID, translation.Text)
			//	for _, word := range translation.Words {
			//		fmt.Printf("	  Word - Begin Time：%d, End Time：%d, Text：%s\n", word.BeginTime, word.EndTime, word.Text)
			//	}
			//}
			//
			//transcription := event.Payload.Output.Transcription
			//fmt.Printf("	识别结果 - Sentence ID：%d, Text：%s\n", transcription.SentenceID, transcription.Text)
			//for _, word := range transcription.Words {
			//	fmt.Printf("	  Word - Begin Time：%d, End Time：%d, Text：%s\n", word.BeginTime, word.EndTime, word.Text)
			//}
			return false
		}
	case "task-finished":
		fmt.Println("任务完成")
		taskDone <- true
		return true
	case "task-failed":
		handleTaskFailed(event, connGummy)
		taskDone <- true
		return true
	default:
		log.Printf("预料之外的事件：%v", event)
	}
	return false
}

// 处理任务失败事件
func handleTaskFailed(event Event, conn *websocket.Conn) {
	if event.Header.ErrorMessage != "" {
		log.Fatalf("任务失败：%s", event.Header.ErrorMessage)
	} else {
		log.Fatal("未知原因导致任务失败")
	}
}

// 关闭连接
func CloseConnection(conn *websocket.Conn) {
	if conn != nil {
		conn.Close()
	}
}
